const apiObj = require('api')
const request = require('base')
const synctool = require('synctool')
const fixcolumnObj = require('fixcolumns')

// token有效时长。从登录时算起
const TokenTime = 1000 * 60 * 60 * 24 * 30
// 字段固定值的更新值。更新了云函数后，要来这里更新date
const fixcolumnsUpdate = '20250514'
// 多语言数据的更新值。更新了多语言云函数后，要来这里更新date
const languageUpdate = {
	'zh-CN': {
		name: '简体中文',
		date: '20241101',
	},
	'zh-TW': {
		name: '正體中文',
		date: '20241101',
	},
	'en': {
		name: 'English',
		date: '20241101',
	}
}

// 获取项目信息
const getTarget = (code) => {
	return new Promise((resolve, reject) => {
		if (0) {
			// 向公共数据库请求项目数据
			request.get({space: request.basedata.CommonSpaceName, name: 'target', where: {code}}).then(res => {
				if (res.data.length > 0) {
					resolve(res.data[0])
				} else {
					reject(request.getError('项目不存在', 904))
				}
			}).catch(reject)
		} else {
			const target = require('./target')
			resolve(target)
		}
	})
}
// 项目状态判断
const handleTargetStatus = (target, Apply) => {
	return new Promise((resolve, reject) => {
		const {common: {startTime}, getError} = request
		const {status, apply, time, attachTime} = target
		if (apply && apply.indexOf(Apply) > -1) {
			if (time) {
				if (time[0] < startTime) {
					const lastTime = attachTime && attachTime > time[1] ? attachTime : time[1]
					if (lastTime > startTime) {
						if (status === 4) {
							reject(getError('项目已关闭', 905))
						} else {
							resolve()
						}
					} else {
						reject(getError('项目已过期', 901))
					}
				} else {
					reject(getError('项目未生效', 902))
				}
			}
		} else {
			reject(getError('项目不合法', 903))
		}
	})
}

/**
 * 系统启动
 * 所有的参数data：
 * code：项目代码 - 该值不一定有，一般不建议传，不传的话就写死了。如果该云服务空间绑定了多个项目则需要传
 * 		通过项目代码获取项目信息
 * user_id：用户id
 * basevalue：字典基础值的更新值
 * basedata：云服务空间的更新值
 * language：多语言文件的更新值。以+隔开，前部分是语言类型；后部分是当前语言的更新时间
 * theme：主题信息的数组的更新值
 * fixcolumns：字段固定信息的更新值
 * api：api接口的更新值
 * 
 * pageKey：记录启动页
 * isTest：代码设置的测试状态
 * domain：启动域名。h5时有效
 */
module.exports = (data) => {
	return new Promise((resolve, reject) => {
		var {code, user_id, Authorization, basevalue, basedata, language, theme, fixcolumns, api, Apply, Development, pageKey, isTest, domain} = data
		const {common, getResult} = request
		const {startTime} = common
		if (!code) {
			// 默认启动该云服务空间绑定的项目
			code = request.basedata.current
		}
		if (code) {
			if (!user_id) { // 通过Authorization获取用户id，并判别是否过期
				if (Authorization) {
					request.token.verify(Authorization, {onlyAnalyse: true}, res => {
						const {User, Target, Login} = res
						if (Target === code) {
							if (Login + TokenTime > Date.now()) {
								user_id = User
							}
						}
					})
				}
			}
			const result = {}
			/**
			 * 通过code获取项目信息
			 * 并且判断有效性
			 */
			getTarget(code).then(target => {
				result.data = target
				// 判断项目状态
				handleTargetStatus(target, Apply).then(res => {
					/**
					 * 判断是否测试环境
					 * 请注意，该值决定了是否写入测试数据库
					 * 开发状态下，一般一定是测试环境。也可以指定为true
					 * 生产状态下，一般是读取项目信息，以决定是否测试环境
					 * 0：表示该值在启动方法后会被重新赋值（start.isTest）
					 * 
					 * 如果其isTest是布尔值，直接决定
					 * 如果是0，表示开发状态下是测试环境；生产状态下是正式环境
					 * 如果是1以及非0，表示开发状态下是测试环境；生产状态下是读取项目设置信息
					 */
					// 确定是否测试环境
					if (typeof(isTest) === 'boolean') {
						// 直接决定
					} else {
						if (isTest === 0) {
							// 如果是0，表示开发状态下是测试环境；生产状态下是正式环境
							isTest = !!Development
						} else {
							// 如果是1以及非0，表示开发状态下是测试环境；生产状态下是读取项目设置信息
							if (Development) {
								isTest = true
							} else {
								/**
								 * 读取项目设置信息
								 * 如果设置了有正式发布的域名，则当前是正式发布得到域名内才是正式环境，其它情况都是读取target.isTest
								 */
								if (domain && target.domain && target.domain.length > 0) {
									// 有些网址发布后会增加index.html，需要去掉
									if (domain.indexOf('/index.html') > -1) {
										domain = domain.split('/index.html')[0]
									}
									isTest = target.domain.indexOf(domain) === -1
								} else {
									// 默认是测试环境
									isTest = typeof(target.isTest) === 'boolean' ? target.isTest : true
								}
							}
						}
					}
					result.isTest = isTest
					// 对比云服务空间的更新值
					if (!basedata || basedata !== request.basedata.date) {
						if (0) {
							// 严谨时，应该要执行
							const {space, other} = target
							Object.keys(request.basedata).forEach(key => {
								if (request.basedata[key].spaceId) {
									if (space === key || (other && other.indexOf(key) > -1)) {
										// 该云服务空间是该项目所需的
									} else {
										delete request.basedata[key]
									}
								}
							})
						}
						/**
						 * 加密云服务空间信息
						 * 前端解密后却没法获取完整的数据长度，导致解密失败
						 * 对策：只对关键信息加密，不再全部加密了
						 */
						result.basedata = synctool.basedata.enBasedata(request.basedata, startTime)
					}
					// 对比Api接口的更新值
					if (!api || api !== apiObj.date) {
						/**
						 * 有必要根据参数对接口做一些取舍
						 */
						Object.keys(apiObj).forEach(key => {
							if (typeof(apiObj[key]) === 'object') {
								delete apiObj[key].return
								delete apiObj[key].description
							}
						})
						result.api = apiObj
					}
					// 用户信息、多语言信息、主题信息、字典信息、字段固定信息需要分别处理
					var index = 0
					// 处理最后的结果
					const handleResut = () => {
						index ++
						if (index === 5) {
							resolve(getResult(result))
						}
					}
					// 获取用户信息
					if (user_id) {
						const login = require('./login')
						login({user_id}, {
							Target: code, Prefix: target.prefix, Partya: target.partya, Test: isTest, Apply, Development, Device: request.common.clientInfo.deviceId
						}).then(res => {
							result.user = res.data
							result.token = res.token
							handleResut()
						}).catch(err => {
							handleResut()
						})
					} else {
						handleResut()
					}
					/**
					 * 对比多语言的更新值
					 * 无论如何都会返回一个list，表示当前有几种多语言选项
					 */
					const languagelist = []
					Object.keys(languageUpdate).forEach(key => {
						languagelist.push({
							text: languageUpdate[key].name,
							value: key
						})
					})
					result.language = {list: languagelist}
					if (language) {
						const arr = language.split('+')
						if ((arr.length === 1 && languageUpdate[arr[0]]) || (arr.length === 2 && languageUpdate[arr[0]] && languageUpdate[arr[0]].date !== languageUpdate[arr[1]])) {
							uniCloud.callFunction({name: 'b-language', data: {type: arr[0], date: arr.length === 2 ? arr[1] : undefined}}).then(res => {
								result.language = res.result.data
								result.language.date = languageUpdate[arr[0]].date
								handleResut()
							}).catch(err => {
								handleResut()
							})
						} else {
							handleResut()
						}
					} else {
						handleResut()
					}
					// 对比字段固定信息的更新值
					if (fixcolumnsUpdate === fixcolumns) {
						handleResut()
					} else {
						result.fixcolumns = fixcolumnObj
						handleResut()
					}
					// 对比主题和基础值字典的最后更新时间
					const {themetimestamp, basevaluetimestamp} = target
					if (theme && theme === themetimestamp) {
						handleResut()
					} else {
						if (0) {
							request.get({space: request.basedata.CommonSpaceName, name: 'theme', where: {target: code}}).then(res => {
								if (res.data.length > 0) {
									result.theme = res.data
								}
								handleResut()
							}).catch(err => {
								handleResut()
							})
						} else {
							handleResut()
						}
					}
					if (basevalue && basevalue === basevaluetimestamp) {
						handleResut()
					} else {
						if (0) {
							request.get({space: request.basedata.CommonSpaceName, name: 'basevalue', where: {target: code}}).then(res => {
								if (res.data.length > 0) {
									result.basevalue = res.data[0]
								}
								handleResut()
							}).catch(err => {
								handleResut()
							})
						} else {
							handleResut()
						}
					}
				}).catch(reject)
			}).catch(err => {
				reject(new Error('没有项目信息'))
			})
		} else {
			reject(new Error('没有项目代码'))
		}
	})
}